package yxy.game.pm2.command.soloride;

import org.joda.time.DateTime;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.soloride;
import yxy.cherry.game.base.message.MessageEmitterHandler;
import yxy.cherry.game.base.message.annotation.MessageSource;
import yxy.cherry.game.base.message.annotation.MessageType;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Hero;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.command.Command;
import yxy.game.pm2.message.SoloRideMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.BattleHandle;
import yxy.game.pm2.module.battle.BattleModule;
import yxy.game.pm2.module.hero.HeroHandle;
import yxy.game.pm2.module.soloride.RankSoloRide;
import yxy.game.pm2.module.soloride.SoloRideHandle;
import yxy.game.pm2.module.soloride.SoloRideHandle.BattleState;
import yxy.game.pm2.module.soloride.SoloRideHandle.SoloRideEntry;
import yxy.game.pm2.module.soloride.SoloRideModule;

import java.util.ArrayList;
import java.util.Collection;

/** 千里走单骑 千里走单骑主界面 */
@MessageType(proto = Command.SoloRideUI, classtype = SoloRideMessage.SoloRideUIRequest.class)
public class CMD_SoloRideUI extends Command<SoloRideMessage.SoloRideUIRequest> {

	@Override
	public void execute(MessageSource messageSource, SoloRideMessage.SoloRideUIRequest request) {
		String playerCode = messageSource.getTag();

		SoloRideMessage.SoloRideUIResponse.Builder response = SoloRideMessage.SoloRideUIResponse.newBuilder();

		SoloRideModule soloRideModule = SoloRideModule.get(playerCode);
		if (soloRideModule == null) {
			send(messageSource, response, Result.ModuleNotOpen);// 模块没开启
			return;
		}

		try {
			if (soloRideModule.tryLock()) {
				if (soloRideModule.isBattling()) {
					DateTime now = DateTime.now();
					SoloRideEntry soloRideEntry = new SoloRideEntry(soloRideModule);
					SoloRideHandle.BattleState state = handleBattle(playerCode, soloRideEntry, 1, now);
					soloRideModule = soloRideEntry.resetModule(soloRideModule);
					soloRideModule.set();

					switch (state) {
					case 局中战斗: {
						ArrayList<SoloRideMessage.SoloRideBattle> resps = new ArrayList<>();
						BattleHandle battleHandle = new BattleHandle();
						CurrencyHandle currencyHandle = new CurrencyHandle();
						// 推送当前的战斗
						for (BattleModule battleModule : soloRideEntry.getBattleModules()) {
							if (now.isBefore(battleModule.timeline().getEndTime())) {
								SoloRideMessage.SoloRideBattle.Builder builder = SoloRideMessage.SoloRideBattle.newBuilder();
								builder.setPlayback(battleHandle.playback(battleModule));
								builder.addAllRewards(currencyHandle.packItems(battleModule.getSettlement().reward()));
								resps.add(builder.build());
							}
						}
						sendChanllengeBattling(messageSource, soloRideModule, resps);
					}
						return;
					case 局间选将: {
						sendChangeHero(messageSource, soloRideModule);
					}
						return;
					case 战斗结算: {
						BattleModule battleModule = soloRideEntry.getSettleBattle();
						battleModule.getSettlement().settle();
						soloRideModule = SoloRideModule.get(playerCode);
						sendChanllengeBattleClear(messageSource, battleModule);
					}
						break;
					default:
						break;
					}

				}

				response.setBest(soloRideModule.getBest());
				response.setStart(soloRideModule.startStage());
				response.setToday(soloRideModule.getToday());

				response.addAllBox(soloRideModule.rewardBox());

				RankSoloRide rankSoloRide = RankSoloRide.getRank(playerCode);
				Collection<RankEntry> top = rankSoloRide.top(3);
				int rank = 0;
				for (RankEntry entry : top) {
					String pCode = entry.getKey();
					int best = entry.getValue().intValue();
					PlayerBean playerBean = PlayerBean.get(pCode);

					SoloRideMessage.TopSoloRide.Builder builder = SoloRideMessage.TopSoloRide.newBuilder();
					builder.setRank(++rank);
					builder.setBest(best);
					builder.setName(playerBean.getName());
					response.addTop(builder);
				}
				{
					int playerRank = rankSoloRide.rank(playerCode);
					response.setRank(playerRank);
				}

				send(messageSource, response, Result.Success);
			}
		} catch (Exception e) {
			e.printStackTrace();
			send(messageSource, response, Result.DataError);
		} finally {
			soloRideModule.unlock();
		}
	}

	private void send(MessageSource messageSource, SoloRideMessage.SoloRideUIResponse.Builder response, Result result) {
		response.setResult(result.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private void sendChangeHero(MessageSource messageSource, SoloRideModule soloRideModule) throws Exception {
		soloRideModule.best(soloRideModule.getCurrent());
		soloRideModule.set();

		String playerCode = messageSource.getTag();

		SoloRideMessage.SoloRideSelectHeroResponse.Builder response = SoloRideMessage.SoloRideSelectHeroResponse.newBuilder();

		HeroHandle heroHandle = new HeroHandle();
		Collection<Hero> heros = heroHandle.getHeros(playerCode);
		for (Hero hero : heros) {
			try {
				response.addHeros(heroHandle.getHeroSimple(playerCode, hero));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (soloRideModule.getHero() != null) {
			response.setHero(soloRideModule.getHero().getCode());
		}

		response.setResult(Result.Success.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private void sendChanllengeBattling(MessageSource messageSource, SoloRideModule soloRideModule, ArrayList<SoloRideMessage.SoloRideBattle> resps) {
		SoloRideMessage.SoloRideChanllengeExecuteResponse.Builder response = SoloRideMessage.SoloRideChanllengeExecuteResponse.newBuilder();
		response.addAllBattleResp(resps);
		response.setBest(soloRideModule.getBest());
		response.addAllBox(soloRideModule.rewardBox());
		response.setResult(Result.Success.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private void sendChanllengeBattleClear(MessageSource messageSource, BattleModule battleModule) {
		SoloRideMessage.SoloRideChanllengeBattleClearResponse.Builder response = SoloRideMessage.SoloRideChanllengeBattleClearResponse.newBuilder();
		response.setInfo(new BattleHandle().battleClear(battleModule));
		response.addAllRewards(new CurrencyHandle().packItems(Currency.merge(battleModule.getSettlement().reward())));
		response.setResult(Result.Success.packResult());
		MessageEmitterHandler.getInstance().send(messageSource, response.build());
	}

	private SoloRideHandle.BattleState handleBattle(String playerCode, SoloRideEntry soloRideEntry, int round, DateTime now) {
		if (!soloRideEntry.isBattling()) {
			return BattleState.没有在战斗;
		}
		if (soloRideEntry.getBattleModules().size() <= 0) {
			soloRideEntry.setBattling(false);
			return BattleState.没有在战斗;
		}
		BattleModule battleModule = soloRideEntry.getLastBattle();
		if (battleModule == null) {
			soloRideEntry.setBattling(false);
			return BattleState.没有在战斗;
		}
		DateTime lastBattleEndTime = battleModule.timeline().getEndTime();
		if (lastBattleEndTime != null && now.isBefore(lastBattleEndTime)) {
			System.err.println(now);
			System.err.println(lastBattleEndTime);
			return BattleState.局中战斗;
		}

		if (!battleModule.getBattleResult().equals(BattleResult.LEFT_WIN)) {
			// 输了结算
			soloRideEntry.setSettleBattle(battleModule);
			return BattleState.战斗结算;
		}

		DateTime startTime = lastBattleEndTime.plusMinutes(SoloRideHandle.minuteRestPeriod());
		if (soloRideEntry.getTickTime().isAfter(lastBattleEndTime)) {
			startTime = soloRideEntry.getTickTime().plusMinutes(SoloRideHandle.minuteRestPeriod());
		}
		if (now.isBefore(startTime)) {
			int stage = soloRideEntry.getStage() + 1;
			soloride data = DataCenter.getData(stage, soloride.class);
			if (data == null) {
				// 已经完成最后一关
				soloRideEntry.setSettleBattle(battleModule);
				return BattleState.战斗结算;
			}

			// 选将
			return BattleState.局间选将;
		}
		if (round >= 10) {
			soloRideEntry.setSettleBattle(battleModule);
			return BattleState.战斗结算;
		}
		soloRideEntry.getBattleModules().clear();
		new SoloRideHandle().battle(playerCode, null, startTime, soloRideEntry);
		return handleBattle(playerCode, soloRideEntry, round + 1, now);
	}

}